// Copyright (c) 2022 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CONTENT_RENDERER_MEDIA_OHOS_MEDIA_PLAYER_RENDERER_CLIENT_H_
#define CONTENT_RENDERER_MEDIA_OHOS_MEDIA_PLAYER_RENDERER_CLIENT_H_

#include <memory>

#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "media/base/native_texture_wrapper.h"
#include "media/base/media_resource.h"
#include "media/base/renderer.h"
#include "media/base/renderer_client.h"
#include "media/base/video_renderer_sink.h"
#include "media/base/video_util.h"
#include "media/base/video_util_ext.h"
#include "media/mojo/clients/mojo_renderer.h"
#include "media/mojo/clients/mojo_renderer_wrapper.h"
#include "media/mojo/mojom/renderer_extensions.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace content {

class OHOSMediaPlayerRendererClient
    : public media::mojom::MediaPlayerRendererClientExtension,
      public media::MojoRendererWrapper {
 public:
  using RendererExtention = media::mojom::MediaPlayerRendererExtension;
  using ClientExtention = media::mojom::MediaPlayerRendererClientExtension;
  OHOSMediaPlayerRendererClient(
      mojo::PendingRemote<RendererExtention> renderer_extension_remote,
      mojo::PendingReceiver<ClientExtention> client_extension_receiver,
      scoped_refptr<base::SequencedTaskRunner> media_task_runner,
      scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
      std::unique_ptr<media::MojoRenderer> mojo_renderer,
      media::ScopedNativeTextureWrapper native_texture_wrapper,
      media::VideoRendererSink* sink);
  ~OHOSMediaPlayerRendererClient() override;

  OHOSMediaPlayerRendererClient(const OHOSMediaPlayerRendererClient&) = delete;
  OHOSMediaPlayerRendererClient& operator=(
      const OHOSMediaPlayerRendererClient&) = delete;

  // Renderer implementation.
  void Initialize(media::MediaResource* media_resource,
                  media::RendererClient* client,
#if BUILDFLAG(ARKWEB_VIDEO_ASSISTANT)
                  media::RequestSurfaceCB request_surface_cb,
                  media::VideoDecoderChangedCB decoder_changed_cb,
#endif // ARKWEB_VIDEO_ASSISTANT
                  media::PipelineStatusCallback init_cb) override;
  media::RendererType GetRendererType() override;

  // media::mojom::MediaPlayerRendererClientExtension implementation
  void OnDurationChange(base::TimeDelta duration) override;
  void OnVideoSizeChange(const gfx::Size& size) override;
  void OnFrameUpdate(media::mojom::OhosSurfaceBufferHandlePtr
                         ohos_surface_buffer_handle) override;
  void OnFrameAvailable();

 private:
  void OnStreamTextureWrapperInitialized(media::MediaResource* media_resource,
                                         bool success);
  void OnSurfaceCreated(int native_window_id);
  void OnSurfaceDestroyed();

  void OnRemoteRendererInitialized(media::PipelineStatus status);
  void OnFinishPaintCallback();

  void PaintNV12VideoFrame(const gfx::Size& coded_size,
                           const gfx::Rect& visible_rect,
                           const gfx::Size& natural_size,
                           uint8_t* mapped,
                           const uint32_t& buffer_size,
                           const int& fd,
                           const int& fd_browser);

  raw_ptr<media::MediaResource> media_resource_ = nullptr;

  // Add native texture impl
  media::ScopedNativeTextureWrapper native_texture_wrapper_;

  raw_ptr<media::RendererClient> client_ = nullptr;

  raw_ptr<media::VideoRendererSink> sink_ = nullptr;

  scoped_refptr<base::SequencedTaskRunner> media_task_runner_;

  scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;

  media::PipelineStatusCallback init_cb_;

  std::vector<uint8_t> resize_buf_;

  // This class is constructed on the main task runner, and used on
  // |media_task_runner_|. These member are used to delay calls to Bind() for
  // |renderer_extension_ptr_| and |client_extension_binding_|, until we are on
  // |media_task_runner_|.
  // Both are set in the constructor, and consumed in Initialize().
  mojo::PendingReceiver<ClientExtention>
      delayed_bind_client_extension_receiver_;
  mojo::PendingRemote<RendererExtention>
      delayed_bind_renderer_extention_remote_;

  // Used to call methods on the MediaPlayerRenderer in the browser process.
  mojo::Remote<RendererExtention> renderer_extension_remote_;

  // Used to receive events from MediaPlayerRenderer in the browser process.
  mojo::Receiver<MediaPlayerRendererClientExtension> client_extension_receiver_{
      this};

  int native_window_id_ = -1;

#if BUILDFLAG(ARKWEB_VIDEO_ASSISTANT)
  media::RequestSurfaceCB request_surface_cb_;
  media::VideoDecoderChangedCB decoder_changed_cb_;
#endif // ARKWEB_VIDEO_ASSISTANT

  // NOTE: Weak pointers must be invalidated before all other member variables.
  base::WeakPtrFactory<OHOSMediaPlayerRendererClient> weak_factory_{this};
};

}  // namespace content

#endif  // CONTENT_RENDERER_MEDIA_OHOS_MEDIA_PLAYER_RENDERER_CLIENT_H_
